Warn about unused TOML keys
authorAlex Crichton <alex@alexcrichton.com>
Fri, 27 Jun 2014 05:53:05 +0000 (22:53 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Sat, 28 Jun 2014 22:18:44 +0000 (15:18 -0700)
Closes #27

libs/toml-rs
src/cargo/core/manifest.rs
src/cargo/core/shell.rs
src/cargo/ops/cargo_compile.rs
src/cargo/util/toml.rs
tests/support/mod.rs
tests/test_cargo_compile.rs

index 7ba80c5ac4a3f6bc3801bb4ac86fd65a569a07ba..713816102b1cb61f45d2306f38e3d95dfdcc8ae1 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7ba80c5ac4a3f6bc3801bb4ac86fd65a569a07ba
+Subproject commit 713816102b1cb61f45d2306f38e3d95dfdcc8ae1
index f9b4c0e1840c8eabf4b21483d7aefd1b4cc80adb..ffd1e6eee988a5cf33aa5afad3581ec24a9cee31 100644 (file)
@@ -20,6 +20,7 @@ pub struct Manifest {
     target_dir: Path,
     sources: Vec<SourceId>,
     build: Option<String>,
+    unused_keys: Vec<String>,
 }
 
 impl Show for Manifest {
@@ -192,6 +193,7 @@ impl Manifest {
             target_dir: target_dir.clone(),
             sources: sources,
             build: build,
+            unused_keys: Vec::new(),
         }
     }
 
@@ -234,6 +236,14 @@ impl Manifest {
     pub fn get_build<'a>(&'a self) -> Option<&'a str> {
         self.build.as_ref().map(|s| s.as_slice())
     }
+
+    pub fn add_unused_key(&mut self, s: String) {
+        self.unused_keys.push(s)
+    }
+
+    pub fn get_unused_keys<'a>(&'a self) -> &'a [String] {
+        self.unused_keys.as_slice()
+    }
 }
 
 impl Target {
index 73f91587cf9cc85cd08cdd57904c1933f0d5644b..32ca19934c68f546e30618326743a596e1838d03 100644 (file)
@@ -1,6 +1,6 @@
 use term;
 use term::{Terminal,color};
-use term::color::{Color, BLACK, RED, GREEN};
+use term::color::{Color, BLACK, RED, GREEN, YELLOW};
 use term::attr::{Attr, Bold};
 use std::io::{IoResult, stderr};
 use std::fmt::Show;
@@ -63,6 +63,10 @@ impl MultiShell {
     pub fn error<T: ToStr>(&mut self, message: T) -> IoResult<()> {
         self.err().say(message, RED)
     }
+
+    pub fn warn<T: ToStr>(&mut self, message: T) -> IoResult<()> {
+        self.err().say(message, YELLOW)
+    }
 }
 
 pub type ShellCallback<'a> = |&mut Shell|:'a -> IoResult<()>;
index 9e8b4d4b053165b3f879616a1c913e0e4a5f9c6e..f8a1b9e231b613b31a3f9b87e7dc75b5401060aa 100644 (file)
@@ -43,6 +43,10 @@ pub fn compile(manifest_path: &Path, update: bool,
     let package = try!(source.get_root_package());
     debug!("loaded package; package={}", package);
 
+    for key in package.get_manifest().get_unused_keys().iter() {
+        try!(shell.warn(format!("unused manifest key: {}", key)));
+    }
+
     let override_ids = try!(source_ids_from_config());
     let source_ids = package.get_source_ids();
 
index 784311f9ce2cae8ad3deb44fa3fb78e2fe42479d..e220a60d5ba4ea9c2c1c58fff6a74241d7b1d842 100644 (file)
@@ -22,9 +22,37 @@ pub fn to_manifest(contents: &[u8],
                                             manifest\n\n{}", e)))
     };
 
-    toml_manifest.to_manifest(source_id).map_err(|err| {
+    let pair = try!(toml_manifest.to_manifest(source_id).map_err(|err| {
         human(format!("Cargo.toml is not a valid manifest\n\n{}", err))
-    })
+    }));
+    let (mut manifest, paths) = pair;
+    match d.toml {
+        Some(ref toml) => add_unused_keys(&mut manifest, toml, "".to_string()),
+        None => {}
+    }
+    return Ok((manifest, paths));
+
+    fn add_unused_keys(m: &mut Manifest, toml: &toml::Value, key: String) {
+        match *toml {
+            toml::Table(ref table) => {
+                for (k, v) in table.iter() {
+                    add_unused_keys(m, v, if key.len() == 0 {
+                        k.clone()
+                    } else {
+                        key + "." + k.as_slice()
+                    })
+                }
+            }
+            toml::Array(ref arr) => {
+                for v in arr.iter() {
+                    add_unused_keys(m, v, key.clone());
+                }
+            }
+            _ => m.add_unused_key(key),
+        }
+    }
+
+
 }
 
 pub fn parse(toml: &str, file: &str) -> CargoResult<toml::Table> {
@@ -126,9 +154,9 @@ impl TomlManifest {
                             (Some(string.clone()), SourceId::for_central())
                         },
                         DetailedDep(ref details) => {
-                            let reference = details.branch.as_ref().map(|b| b.clone())
-                                .or_else(|| details.tag.as_ref().map(|t| t.clone()))
-                                .or_else(|| details.rev.as_ref().map(|t| t.clone()))
+                            let reference = details.branch.clone()
+                                .or_else(|| details.tag.clone())
+                                .or_else(|| details.rev.clone())
                                 .unwrap_or_else(|| "master".to_str());
 
                             let new_source_id = match details.git {
@@ -161,11 +189,14 @@ impl TomlManifest {
         }
 
         let project = self.project.as_ref().or_else(|| self.package.as_ref());
-        let project = try!(project.require(|| human("No `package` or `project` section found.")));
+        let project = try!(project.require(|| {
+            human("No `package` or `project` section found.")
+        }));
 
+        let pkgid = try!(project.to_package_id(source_id.get_location()));
+        let summary = Summary::new(&pkgid, deps.as_slice());
         Ok((Manifest::new(
-                &Summary::new(&try!(project.to_package_id(source_id.get_location())),
-                              deps.as_slice()),
+                &summary,
                 targets.as_slice(),
                 &Path::new("target"),
                 sources,
index 39f5eef86a452ac41fbd1dd74e34d7873c68e860..2a7bc40575c66672803a7a58fcfaa4bd9adf842d 100644 (file)
@@ -360,7 +360,7 @@ pub fn escape_path(p: &Path) -> String {
 
 pub fn basic_bin_manifest(name: &str) -> String {
     format!(r#"
-        [project]
+        [package]
 
         name = "{}"
         version = "0.5.0"
index 168603d22f9df4aa03250f18bf21a2bf59fff4ed..f7497360ae538e62ca4a3361df61d9fdd6c135a2 100644 (file)
@@ -559,3 +559,47 @@ test!(many_crate_types {
     assert!(file0.ends_with(os::consts::DLL_SUFFIX) ||
             file1.ends_with(os::consts::DLL_SUFFIX));
 })
+
+test!(unused_keys {
+    let mut p = project("foo");
+    p = p
+        .file("Cargo.toml", r#"
+            [project]
+
+            name = "foo"
+            version = "0.5.0"
+            authors = ["wycats@example.com"]
+            bulid = "foo"
+
+            [[lib]]
+
+            name = "foo"
+        "#)
+        .file("src/foo.rs", r#"
+            pub fn foo() {}
+        "#);
+    assert_that(p.cargo_process("cargo-build"),
+                execs().with_status(0)
+                       .with_stderr("unused manifest key: project.bulid\n"));
+
+    let mut p = project("bar");
+    p = p
+        .file("Cargo.toml", r#"
+            [project]
+
+            name = "foo"
+            version = "0.5.0"
+            authors = ["wycats@example.com"]
+
+            [[lib]]
+
+            name = "foo"
+            build = "foo"
+        "#)
+        .file("src/foo.rs", r#"
+            pub fn foo() {}
+        "#);
+    assert_that(p.cargo_process("cargo-build"),
+                execs().with_status(0)
+                       .with_stderr("unused manifest key: lib.build\n"));
+})